import UIKit
import Alamofire
import AliyunOSSiOS
import SwiftyJSON



class VGUpVideoManager: NSObject {
    typealias UploadCallback = (([String:String]) -> Void)
    
    fileprivate var uploader: VODUploadClient!
    
    fileprivate var progressClosure: ((Progress) -> Void)?
    
    fileprivate var completionClosure: UploadCallback?
    
    fileprivate var faliedClosure: ((String) -> Void)?
    
    fileprivate var requestCount:Int = 0
    
    override init() {
        super.init()
        self.uploader = VODUploadClient()
    }
    
    fileprivate func setupListener(definition:String,auth:String,address:String,videoId:String) {
        
        let finishListener: OnUploadFinishedListener = { (fileInfo, result) in
            
            if let resultVideoId = result?.videoId{
                print(resultVideoId, result!.imageUrl ?? "空")
                self.getVideoPath(vid: resultVideoId, completionClosure: self.completionClosure!)
                
            }else{
                self.getVideoPath(vid: videoId, completionClosure: self.completionClosure!)
            }
            
        }
        
        /**
         上传失败回调
         @param fileInfo 上传文件信息
         @param code 错误码
         @param message 错误描述
         */
        let failedListener: OnUploadFailedListener = { (fileInfo, code, message) in
            print(code!, message!)
            self.faliedClosure?(message!)
        }
        
        /**
         上传进度回调
         @param fileInfo 上传文件信息
         @param uploadedSize 已上传大小
         @param totalSize 总大小
         */
        let progressListener: OnUploadProgressListener = { (fileInfo, uploadedSize, totalSize) in
            print(uploadedSize, totalSize)
            let pro: Progress = Progress(totalUnitCount: Int64(totalSize))
            if Double(uploadedSize/totalSize) >= 0.98 {
                pro.completedUnitCount = Int64(totalSize*98/100)
            } else {
                pro.completedUnitCount = Int64(uploadedSize)
            }
            self.progressClosure?(pro)
            print(pro.fractionCompleted)
        }
        
        /**
         token过期回调
         上传地址和凭证方式上传需要调用resumeWithAuth:方法继续上传
         STS方式上传需要调用resumeWithToken:accessKeySecret:secretToken:expireTime:方法继续上传
         */
        let tokenExpiredListener: OnUploadTokenExpiredListener = { ()
            // token过期，设置新的上传凭证，继续上传
            self.uploader.resume(withAuth: auth)
        }
        
        /**
         上传开始重试回调
         */
        let retryListener: OnUploadRertyListener = {
            
        }
        
        /**
         上传结束重试，继续上传回调
         */
        let retryResumeListener: OnUploadRertyResumeListener = {
            
        }
        
        /**
         开始上传回调
         上传地址和凭证方式上传需要调用setUploadAuthAndAddress:uploadAuth:uploadAddress:方法设置上传地址和凭证
         @param fileInfo 上传文件信息
         */
        let uploadStartedListener: OnUploadStartedListener = { fileInfo in
            // 设置上传地址 和 上传凭证
            self.uploader.setUploadAuthAndAddress(fileInfo, uploadAuth: auth, uploadAddress: address)
        }
        
        // 上传地址和凭证方式调用init:方法初始化。
        let listener: VODUploadListener = VODUploadListener()
        listener.finish = finishListener
        listener.failure = failedListener
        listener.progress = progressListener
        listener.expire = tokenExpiredListener
        listener.retry = retryListener
        listener.retryResume = retryResumeListener
        listener.started = uploadStartedListener
        self.uploader.setListener(listener)
        
    }
    
    fileprivate func addToTaskList(cateId: String, path: String,fileName:String) {
        
        // 添加文件到上传列表
        let filePath: String = path
        let cateId: String = cateId
        let vodInfo: VodInfo = VodInfo()
        //标题
        vodInfo.title = fileName
        //分类id
        vodInfo.cateId = NSNumber(integerLiteral: Int(cateId) ?? 2061)
        self.uploader.addFile(filePath, vodInfo: vodInfo)
    }
    
    fileprivate func requestAuthAndAddress(cateId: String, fileName: String,templateGroupId:String,userData:String,definition:String){
        let params :Parameters = [
            "fileName":fileName,
            "title":fileName,
            "templateGroupId":templateGroupId,
            "cateId":cateId,
            "UserData":userData]
        
        
        self.postRequestWithBodyFor(strUrl:NetConstants.APP_ALIYUN_GET_AUTH,
                                    body:params, responseString: {(response) in
            if response.value == nil{
                return
            }
            if let json = try? JSON.init(data: response.data!){
                print(json)
                guard let auth = json.dictionary?["data"]?.dictionary?["uploadAuth"]?.stringValue,
                      let address = json.dictionary!["data"]?.dictionary!["uploadAddress"]?.stringValue,
                      let videoId = json.dictionary!["data"]?.dictionary!["videoId"]?.stringValue
                else {
                    self.faliedClosure?("授权失败\(json.dictionary?["data"]?.dictionary?["msg"]?.stringValue ?? "")")
                    return
                }
                self.setupListener(definition:definition,auth:auth,address:address,videoId: videoId)
                //开始上传
                self.uploader.start()
                
                
            }else{
                self.faliedClosure?("授权失败")
                return
            }
            
        }
        )
        
    }
    
    func upload(id:String,cateId: String, path: String,templateGroupId:String,definition:String,userData:String,fileName: String,progressClosure: ((Progress) -> Void)?, completionClosure: UploadCallback?, faliedClosure: ((String) -> Void)?){
        
        self.progressClosure = progressClosure
        
        self.completionClosure = completionClosure
        
        self.faliedClosure = faliedClosure
        
        self.addToTaskList(cateId: cateId, path: path,fileName: fileName)
        
        self.requestAuthAndAddress(cateId: cateId, fileName: fileName,templateGroupId: templateGroupId,userData: userData,definition: definition)
    }
    
    fileprivate func getVideoPath(vid:String, definition:String = "SD,HD",completionClosure: @escaping UploadCallback) {
        
        
        
        if requestCount <= 40 {
            
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3.0) { [weak self] in
                
                self?.postRequestWithBodyFor(strUrl:NetConstants.APP_ALIYUN_GET_ADDRESS, body: ["videoId":vid,"definition": definition ],responseString: {(response) in
                    print(NetConstants.APP_ALIYUN_GET_ADDRESS + "?" + "outputType=oss" + "&videoId=\(vid)")
                    if let json = try? JSON.init(data: response.data! ){
                        if(!json["success"].boolValue){
                            self?.requestCount += 1
                            self?.getVideoPath(vid:vid,definition: definition,completionClosure: completionClosure)
                            return
                        }
                        
                        var hdUrl = ""
                        var hdFileSize = ""
                        
                        var sdUrl = ""
                        var sdFileSize = ""
                        
                        if let playInfoList = json.dictionaryValue["data"]?.dictionaryValue["playInfoList"]{
                            
                            if playInfoList.count != definition.split(separator: ",").count{
                                self?.requestCount += 1
                                self?.getVideoPath(vid:vid,completionClosure: completionClosure)
                                return
                            }
                            
                            if let hdPlayInfo:[String: JSON] = playInfoList.arrayValue.first(where: {$0.dictionaryValue["definition"]?.stringValue == "HD"})?.dictionaryValue {
                                //hd视频信息
                                hdUrl = hdPlayInfo["playURL"]?.stringValue ?? ""
                                hdFileSize = hdPlayInfo["size"]?.stringValue ?? ""
                            }
                            
                            if let sdPlayInfo:[String: JSON] = playInfoList.arrayValue.first(where: {$0.dictionaryValue["definition"]?.stringValue == "SD"})?.dictionaryValue {
                                //sd视频信息
                                sdUrl = sdPlayInfo["playURL"]?.stringValue ?? ""
                                sdFileSize = sdPlayInfo["size"]?.stringValue ?? ""
                            }
                            
                            
                        }
                        
                        
                        
                        var pic = ""
                        
                        if let picPath: String = json.dictionary!["data"]?.dictionary!["videoBase"]?.dictionary!["coverURL"]?.stringValue {
                            if picPath.contains(".jpg?") {
                                pic = picPath.components(separatedBy: ".jpg?").first! + ".jpg"
                            }else{
                                pic = picPath;
                            }
                        }
                        
                        //                        if videoPath!.contains(".mp4?")  {
                        //                            video = videoPath!.components(separatedBy: ".mp4?").first! + ".mp4"
                        //                        }else{
                        //                            video = videoPath!
                        //                        }
                        
                        let resultDict = ["url":hdUrl,
                                          "fileSize":hdFileSize,
                                          "coverUrl":pic,
                                          "videoId":vid,
                                          "sdVideo":sdUrl,
                                          "sdStorage":sdFileSize]
                        
                        print(resultDict.debugDescription)
                        completionClosure(resultDict)
                    } else {
                        self?.requestCount += 1
                        self?.getVideoPath(vid:vid,completionClosure: completionClosure)
                    }
                    return
                })
                
            }
        }
    }
    
    
    /**
     * post 接口请求
     * @para strUrl   String 请求地址
     * @para body     Data? 请求参数
     * @para successBack  成功回调
     * @para failureBack  失败回调
     */
    func postRequestWithBodyFor(strUrl:String,
                                body:Parameters,
                                responseString :@escaping (AFDataResponse<Any>) -> Void){
        
        
        
        print("请求地址：\(strUrl)\(body)")
        
        
        //            var request = URLRequest.init(url: URL.init(string: strUrl)!)
        //
        //            request.setValue("application/json", forHTTPHeaderField: "Accept")
        //            request.setValue("application/json;charset=UTF-8", forHTTPHeaderField: "Content-Type")
        
        AlamofireManager.shareInstance().request(strUrl,method: .post,parameters:body, encoding:JSONEncoding.default)
            .validate()
            .responseJSON(completionHandler: responseString)
    }
    
    /**
     字典转换为JSONString
     
     - parameter dictionary: 字典参数
     
     - returns: JSONString
     */
    func getJSONStringFromDictionary(dictionary:NSDictionary) -> String {
        if (!JSONSerialization.isValidJSONObject(dictionary)) {
            print("无法解析出JSONString")
            return ""
        }
        let data : Data! = try? JSONSerialization.data(withJSONObject: dictionary, options: []) as Data?
        let JSONString = NSString(data:data as Data,encoding: String.Encoding.utf8.rawValue)
        return JSONString! as String
        
    }
    

    func cancelAll(){
        uploader.stop()
        uploader.clearFiles()
    }
}

